package com.sans.security;

import com.sans.common.util.SecurityUtil;
import com.sans.core.entity.Identity;
import com.sans.core.entity.Role;
import com.sans.core.service.AdminService;
import com.sans.core.service.IdentityService;
import com.sans.security.entity.SelfUserEntity;
import com.sans.security.service.SelfUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.*;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.CredentialsContainer;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * 自定义登录验证
 * @author 123
 */
@Component
public class UserAuthenticationProvider implements AuthenticationProvider {
    @Autowired
    private SelfUserDetailsService selfUserDetailsService;
    @Autowired
    private AdminService adminService;
    @Autowired
    private IdentityService identityService;
    @Autowired
    private HttpServletRequest request;
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        // 获取表单输入中返回的用户名
        String account = (String) authentication.getPrincipal();
        // 获取表单中输入的密码
        String password = (String) authentication.getCredentials();
        // 查询用户是否存在
        SelfUserEntity userInfo = selfUserDetailsService.loadUserByUsername(account);
        System.err.println(userInfo.toString());
        if (userInfo == null) {
            throw new UsernameNotFoundException("用户不存在");
        }
        // 判断密码是否正确，这里我们的密码使用BCryptPasswordEncoder进行加密的
        if (!new BCryptPasswordEncoder().matches(password, userInfo.getPassword())) {
            throw new BadCredentialsException("密码不正确");
        }
        // 判断用户账号状态
        if (userInfo.getAdminStatus() == 0){
            throw new LockedException("该用户已被冻结");
        }
        //身份集合(通过用户ID获取身份集合)
        Set<Identity> identities= new HashSet<>();
        //判断是否有此身份
        String ident = request.getParameter("identity");
        if (ident.equals("")){
            throw new InsufficientAuthenticationException("请选择一个身份");
        }
        //身份信息
        List<Identity> identityList = identityService.selectSysIdentityByUserId(userInfo.getBid());
        for (Identity identity : identityList) {
            identities.add(new Identity("IDENTITY_"+identity.getIdentityName()));
            if (!identity.getIdentityType().equals(Integer.valueOf(ident))){
                throw new InsufficientAuthenticationException("用户身份信息不存在"); //
            }
        }
        userInfo.setIdentities(identities);
        List<Integer> agentId = identityList.stream().map(Identity::getAgentId).collect(Collectors.toList());//代理ID固定
        String s = agentId.toString();//[8]

        List<Integer> identityId = identityList.stream().map(Identity::getIdentityId).collect(Collectors.toList());
        // 角色集合
        Set<GrantedAuthority> authorities = new HashSet<>();
        // 查询用户角色
        List<Role> roleList = adminService.selectSysRoleByUserId(userInfo.getAgentId(),userInfo.getIdentityId());//TODO:根据所选的身份id和代理id查询角色:身份认证时应该获取俩参数
        for (Role role : roleList){
            authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getRoleName()));
        }
        userInfo.setAuthorities(authorities);
        // 进行登录(重写这个方法)
        return new UsernamePasswordAuthenticationToken(userInfo, password, authorities);
    }
    @Override
    public boolean supports(Class<?> authentication) {
        return true;
    }
}